package com.allqj.sfx.ddd.member.application.service;

import com.allqj.sfx.application.TableHeaderApplicationService;
import com.allqj.sfx.application.dto.DictDTO;
import com.allqj.sfx.application.dto.TableColumnDTO;
import com.allqj.sfx.ddd.member.application.assembler.FlowDefAssember;
import com.allqj.sfx.ddd.member.application.dto.FlowDefDTO;
import com.allqj.sfx.ddd.member.domain.entity.flow.FlowApprover;
import com.allqj.sfx.ddd.member.domain.entity.flow.FlowApproverType;
import com.allqj.sfx.ddd.member.domain.entity.flow.FlowDef;
import com.allqj.sfx.ddd.member.domain.entity.flow.FlowType;
import com.allqj.sfx.ddd.member.domain.repository.FlowDefRepository;
import com.allqj.sfx.ddd.member.domain.service.FlowEngineService;
import com.allqj.sfx.ddd.member.domain.service.FlowService;
import com.allqj.sfx.domain.enums.PageEnum;
import com.allqj.sfx.domain.utils.UserContextHolder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author sjw
 * @className UserApplicationService
 * @date 2022/7/20 9:38
 * @description: 业务编排
 * 依赖domain层的service&repository
 * 会员管理-管理端-审批配置
 */

@Component
public class AdminFlowApplicationService {
    private final TableHeaderApplicationService tableHeaderApplicationService;
    private final FlowService flowService;
    private final FlowEngineService flowEngineService;
    private final FlowDefRepository flowDefRepository;

    public AdminFlowApplicationService(TableHeaderApplicationService tableHeaderApplicationService,
                                       FlowService flowService,
                                       FlowEngineService flowEngineService,
                                       FlowDefRepository flowDefRepository) {
        this.tableHeaderApplicationService = tableHeaderApplicationService;
        this.flowService = flowService;
        this.flowEngineService = flowEngineService;
        this.flowDefRepository = flowDefRepository;
    }

    /**
     * 用户管理-列表表头
     *
     * @return
     */
    public List<TableColumnDTO> pageHeader() {
        List<TableColumnDTO> headers = tableHeaderApplicationService.header(PageEnum.MEMBER_ADMIN_FLOW);
        return Optional.ofNullable(headers).orElse(new ArrayList<>());
    }

    /**
     * 模块字典
     *
     * @return
     */
    public List<DictDTO> moduleTypes() {
        List<FlowType> flowTypes = flowService.moduleTypes();
        return flowType2Dict(flowTypes);
    }

    /**
     * 功能字典
     *
     * @param moduleId
     * @return
     */
    public List<DictDTO> functionTypes(Integer moduleId) {
        List<FlowType> flowTypes = flowService.functionTypes(moduleId);
        return flowType2Dict(flowTypes);
    }

    /**
     * 审批人类型字典
     *
     * @return
     */
    public List<DictDTO> approverTypes() {
        List<FlowApproverType> flowApproverTypes = flowService.approverTypes();
        return flowApproverType2Dict(flowApproverTypes);
    }

    /**
     * 新增审批流程
     *
     * @param flowDefDTO
     * @return
     */
    public Integer addFlowDef(FlowDefDTO flowDefDTO) {
        FlowDef flowDef = FlowDefAssember.INSTANCE.dto2Entity(flowDefDTO);
        if (flowDef == null) return null;
        Date now = new Date();
        flowDef.setOperatorId(UserContextHolder.getUserContext().getUserId());
        flowDef.setCreateTime(now);
        flowDef.setModiferId(flowDef.getOperatorId());
        flowDef.setModifyTime(now);
        return flowService.addFlowDef(flowDef);
    }

    /**
     * 修改审批流程
     *
     * @param flowDefDTO
     * @return
     */
    public Integer modifyFlowDef(FlowDefDTO flowDefDTO) {
        FlowDef flowDef = FlowDefAssember.INSTANCE.dto2Entity(flowDefDTO);
        if (flowDef == null || flowDef.getId() == null) return null;
        Date now = new Date();
        flowDef.setModiferId(UserContextHolder.getUserContext().getUserId());
        flowDef.setModifyTime(now);
        return flowService.modifyFlowDef(flowDef);
    }


    private List<DictDTO> flowType2Dict(List<FlowType> flowTypes) {
        if (flowTypes == null) return new ArrayList<>();
        return flowTypes.stream().map(this::flowType2Dict).collect(Collectors.toList());
    }

    private DictDTO flowType2Dict(FlowType flowType) {
        if (flowType == null) return null;
        DictDTO dictDTO = new DictDTO();
        dictDTO.setCode(flowType.getId());
        dictDTO.setName(flowType.getName());
        return dictDTO;
    }

    private List<DictDTO> flowApproverType2Dict(List<FlowApproverType> flowApproverTypes) {
        if (flowApproverTypes == null) return new ArrayList<>();
        return flowApproverTypes.stream().map(this::flowApproverType2Dict).collect(Collectors.toList());
    }

    private DictDTO flowApproverType2Dict(FlowApproverType flowApproverType) {
        if (flowApproverType == null) return null;
        DictDTO dictDTO = new DictDTO();
        dictDTO.setCode(flowApproverType.getId());
        dictDTO.setName(flowApproverType.getName());
        return dictDTO;
    }

    public Integer instance(Integer code, String extParam) {
        return flowEngineService.startInstance(code, extParam, null);
    }

    public Integer pass(Integer instanceId) {
        FlowApprover flowApprover = new FlowApprover(UserContextHolder.getUserContext());
        return flowEngineService.complete(instanceId, flowApprover, null);
    }

    public Integer reject(Integer instanceId) {
        FlowApprover flowApprover = new FlowApprover(UserContextHolder.getUserContext());
        return flowEngineService.reject(instanceId, flowApprover, null);
    }
}
